/* eslint-disable n/no-process-exit */
"use strict";

/* eslint-disable jsdoc/no-restricted-syntax */
// copy from https://github.com/mizdra/css-modules-kit/pull/180/files#diff-36b131f4138b1f3a1248aa25efa7356f197326e7621355e40dcc165d994b0fb6R75
const { stdin, stdout } = require("node:process");

stdin.setEncoding("utf8");
/**
 * @param {*} msg
 * @returns {void}
 */
function send(msg) {
  const json = JSON.stringify(msg);
  const len = Buffer.byteLength(json, "utf8");
  stdout.write(`Content-Length: ${len}\r\n\r\n`);
  stdout.write(json);
}

let buffer = "";
let contentLength = 0;

stdin.on("data", (chunk) => {
  buffer += chunk;

  while (true) {
    if (contentLength === 0) {
      const headerEnd = buffer.indexOf("\r\n\r\n");
      if (headerEnd === -1) return;

      const header = buffer.slice(0, headerEnd);
      const match = header.match(/Content-Length: (\d+)/i);
      if (!match) return; // Ignore malformed headers

      contentLength = Number.parseInt(match[1], 10);
      buffer = buffer.slice(headerEnd + 4);
    }

    // Wait for the full message body
    if (buffer.length < contentLength) return;

    const messageJson = buffer.slice(0, contentLength);
    buffer = buffer.slice(contentLength);
    contentLength = 0; // Reset for the next message

    try {
      const req = JSON.parse(messageJson);

      if (req.method === "initialize") {
        send({
          jsonrpc: "2.0",
          id: req.id,
          result: {
            capabilities: {}, // Minimal capabilities
          },
        });
      } else if (req.method === "shutdown") {
        // Respond to shutdown before exiting
        send({
          jsonrpc: "2.0",
          id: req.id,
          result: null,
        });
        // The client should send 'exit' after this, but we can exit here if needed,
        // though technically LSP spec suggests waiting for 'exit'
        // process.exit(0);
      } else if (req.method === "exit") {
        process.exit(0); // Exit cleanly
      } else if (req.id !== undefined) {
        // Respond with an error for unsupported requests that have an ID
        send({
          jsonrpc: "2.0",
          id: req.id,
          error: {
            code: -32601, // MethodNotFound
            message: `Method not found: ${req.method}`,
          },
        });
      }
      // Ignore notifications (requests without an ID) other than 'exit'
    } catch (error) {
      // Handle JSON parsing errors or other issues
      console.error("Error processing message:", error);
      // Optionally send a generic error response if possible
    }
  }
});

stdin.on("end", () => {
  // Handle stream end if necessary
  process.exit(0);
});

// Handle potential errors on streams
stdin.on("error", (err) => {
  console.error("Stdin Error:", err);
  process.exit(1);
});

stdout.on("error", (err) => {
  console.error("Stdout Error:", err);
  process.exit(1);
});
